Intro Editorial A Propos Sommaire Quizz Musiques Pub Archives
Obligement


Programmation : Amiga E - les bases par Damien Guichard



Les avantages de l'Amiga-E

L'Amiga-E, déjà très populaire auprès des amigaphiles, est dans une période de renaissance avec le compilateur ECX de Leif Salomonsson. ECX est totalement compatible avec EC v3.3a et peut générer aussi bien du code 68020 pour les Amiga classiques que du code PowerPC pour MorphOS. Une version AmigaOne n'est pas prévue mais n'est pas exclue non plus.

Aucun autre langage de programmation ne rend la programmation système plus facile que l'Amiga-E. Parmi les fonctionnalités qui facilitent la vie on peut citer :
  • Les types de bas niveau.
  • Les exceptions légères (elles ne sont pas des objects).
  • Les listes immédiates.

Le résultat c'est un style plus fluide, la programmation système est plus sûre et plus responsable qu'il n'est possible avec d'autres langages sur Amiga.

Normalement un bon style et une relecture soigneuse du code doivent permettre d'éviter le recours à Enforcer, MungWall et autres utilitaires de déboguage système. Il est préférable, autant que possible, de prévenir plutôt que de guérir les bogues de programmation système. Les outils de déboguage avancé peuvent avoir des pouvoirs qui semblent magiques, il n'en reste pas moins qu'ils opèrent au niveau machine, c'est-à-dire à un niveau bien plus bas qu'il n'est souhaitable. Il n'y a pas de meilleure arme contre les bogues qu'une bonne lisibilité du code source. Tout ce qui opère à un niveau plus bas que le code source est de trop bas niveau.

La gestion des ressources

Comme les ressources système sont partagées entre tous les programmes, une stratégie est nécessaire pour garantir une distribution optimale de ces ressources, qui sont toujours trop limitées. La stratégie de l'AmigaOS est rapide et simpliste : le premier demandeur est le premier servi.

Cette stratégie garantie toujours une vitesse maximale, mais requière de la discipline de la part du programmeur pour assurer une distribution optimale :
  • Les ressources doivent être allouées le plus tard possible (au dernier moment).
  • Les ressources doivent être libérées le plus tôt possible.
  • Les allocations et les libérations doivent être "parenthésées".

Les prochains chapitres expliquent ce que "parenthésées" veut dire et en quoi les exceptions de l'Amiga-E simplifient grandement les choses.

Il faut aussi garder à l'esprit que :
  • Toute demande de ressource peut réussir ou échouer.
  • Le programme doit supporter correctement les deux cas.
  • Il faut informer l'utilisateur de l'origine en cas d'erreur.

Les librairies système

Comme vous le savez déjà, les fonctionnalités système résident principalement dans les librairies. Certaines sont en ROM, la plupart sont dans le répertoire Libs: et d'autres (comme Reqtools et MUI) ne sont pas fournies par Commodore mais font néanmoins partie de la pratique de l'Amiga et sont des outils incontournables pour le programmeur.

Les librairies sont donc les ressources de base et la première chose à savoir c'est comment bien les gérer :
  • Autant placer OPT OSVERSION=37 au début de chaque programme, il n'y a aucun intérêt à programmer en dessous de l'OS37.
  • Une librairie s'ouvre avec OpenLibrary(name,version).
  • Spécifez version=37 pour l'OS2.0+ et version=39 pour l'OS3.0+.
  • Retenez le résultat de l'appel dans la variable librarybase.
  • Si le résultat est NIL il n'y a rien d'autre à faire qu'afficher un message d'erreur.
  • Sinon vous pouvez appeler toutes les fonctions de cette librairie.
  • Une fois que vous en avez terminé vous devez appeler CloseLibrary(librarybase).
  • Ensuite vous ne pouvez plus appeler aucune fonction de cette librairie.

La reqtools.library est bien pratique pour afficher des messages d'erreur, c'est pourquoi il est très commode de l'ouvrir avant toute autre chose. Le programme HelloWorld suivant illustre l'ouverture d'une librairie :

OPT OSVERSION=37

MODULE 'reqtools'

PROC main()
  reqtoolsbase:=OpenLibrary('reqtools.library',37)
  IF reqtoolsbase
    RtEZRequestA('Hello World!','OK',0,0,0)
    CloseLibrary(reqtoolsbase)
  ELSE
    PrintF('Could not open reqtools.library!\n')
  ENDIF
ENDPROC

La variable de base est "reqtoolsbase" et "RtEZRequestA" affiche un simple panneau.

Notez que le succès et l'échec sont deux cas distincts et clairement séparés :
  • En cas d'échec d'OpenLibrary : on affiche un message d'erreur (et on ne peut pas utiliser reqtools pour le faire !), on ne ferme pas la librairie.
  • En cas de succès d'OpenLibrary : on peut appeler les fonctions reqtools, et on doit fermer la librairie quand on en a terminé.

C'est ça la gestion "parenthésée" des ressources.

Ressources et exceptions Amiga-E

Le programme précédent est limpide mais pas très réaliste. Un programme réaliste comporte bien davantage de librairies, de fichiers et autres allocations mémoire. Et cette profusion de ressources ne doit pas se faire au détriment de la clarté du code source. On ne peut pas imbriquer des IF indéfiniment, ou alors même le programme le plus simple paraîtra abominablement tortueux. Heureusement, les exceptions Amiga-E permettent de rendre invisible la structuration due à la gestion parenthésée des ressources. La gestion des ressources devient encore plus sûre, et la logique du programme encore plus transparente.

Voici à quoi ressemble le HelloWorld modifié pour les exceptions :

OPT OSVERSION=37

MODULE 'reqtools'

ENUM OK,ERR_NOREQTOOLS

PROC main() HANDLE
  reqtoolsbase:=OpenLibrary('reqtools.library',37)
  IF reqtoolsbase=NIL THEN Raise(ERR_NOREQTOOLS)
  RtEZRequestA('Hello World!','OK',0,0,0)
EXCEPT DO
  SELECT exception
  CASE ERR_NOREQTOOLS
    WriteF('Could not open reqtools.library v37+ !\n')
  ENDSELECT
  IF reqtoolsbase THEN CloseLibrary(reqtoolsbase)
ENDPROC

Cette version peut paraître plus compliquée que la précédente, elle a néanmoins un avantage décisif : ajouter une ressource ne modifie pas la structure du code, ça n'est plus que l'affaire d'un "Open", d'un "Raise", d'un "CASE" et d'un "Close" supplémentaire.

Toutefois n'utilisez pas les exceptions automatiques : elles rendent les choses implicites, ce qui n'est généralement pas une bonne idée. Rendez les choses aussi explicites que possible.

Programme et environnement

Un programme peut être lancé soit à partir du Shell soit à partir du Workbench. Les deux cas doivent être gérés de façon appropriée. La variable "wbmessage" permet de connaître l'environnement de lancement. Si le programme est lancé à partir du Workbench alors on a "wbmessage<>NIL". Si le programme est lancé à partir du Shell alors on a "wbmessage=NIL".

Bien sûr, si le programme est lancé à partir du Shell alors on préfère un message dans la console plutôt qu'un panneau. Il faut alors utiliser "wbmessage" pour distinguer les deux cas.

Une autre attente du Shell c'est le code d'erreur retourné :
  • 0 si tout est OK.
  • ou 5 pour un avertissement (le programme peut tout de même poursuivre).
  • ou 10 pour une erreur (le programme ne peut pas poursuivre).

Et voici à quoi ressemble le HelloWorld modifié pour exploiter au mieux l'environnement de démarrage :

OPT OSVERSION=37

MODULE 'reqtools'

ENUM OK,ERR_NOREQTOOLS

PROC main() HANDLE
  DEF rcode
  reqtoolsbase:=OpenLibrary('reqtools.library',37)
  IF reqtoolsbase=NIL THEN Raise(ERR_NOREQTOOLS)
  display('Hello World!')
EXCEPT DO
  SELECT exception
  CASE ERR_NOREQTOOLS
    WriteF('Could not open reqtools.library v37+ !\n')
    rcode:=10
  DEFAULT
    rcode:=0
  ENDSELECT
  IF reqtoolsbase THEN CloseLibrary(reqtoolsbase)
ENDPROC rcode

PROC display(msg)
  IF wbmessage
    RtEZRequestA(msg,'OK',0,0,0)
  ELSE
    PrintF(msg); PrintF('\n')
  ENDIF
ENDPROC

Pour aller plus loin

La documentation indispensable c'est les Autodocs de Commodore, et c'est encore mieux dans le format AmigaGuide : aminet/dev/misc/AmigaOS_guides.lha

Le compilateur EC v3.3a de Wouter van Oortmerssen (version complète) : wouter.fov120.com/e/

Le compilateur ECX de Leif Salomonsson (version démo). : home.swipnet.se/blubbe/ECX

L'Amiga-E mailing list : www.freelists.org/list/positron